package core;
import fileoperation.FileCreation;
import fileoperation.FileDeletion;
import jitobject.Blob;
import jitobject.JitObject;
import jitobject.Tree;
import repository.Repository;
import zlib.ZLibUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class JitHash {
    /**
     * hash a blob, if exists, overwrite.
     *
     * @param file
     * @throws Exception
     */
    public static void blobHash(File file,String objectsPath) throws Exception {
        Blob blob = new Blob(file);
        String key = blob.getKey();
        if (key.length() != 40) {
            throw new IOException("hash value length error!");
        }

        // create folder
        String hashDir = objectsPath+ File.separator + key.substring(0, 2);
        if (!new File(hashDir).exists()) {
            FileCreation.createDirectory(objectsPath, key.substring(0, 2));
        }
        // create hash file
        String hashFile = hashDir + File.separator + key.substring(2);
        if (!new File(hashFile).exists()) {
            FileCreation.createFile(hashDir, key.substring(2), "");
        }
        // overwrite hash file
        blob.compressWrite(hashFile, blob);

        // generate index info
        String blobPath = file.getCanonicalPath();
        String cutR = "/|\\\\";
        String[] sp = blobPath.split(cutR);
        String[] originalPath = System.getProperty("user.dir").split(cutR);
        int start = originalPath.length;
        String indexInfo = "";
        for(int i = start; i < sp.length; i ++) {
            indexInfo += sp[i];
            if (i != sp.length - 1)
                indexInfo += File.separator;
        }
        indexInfo = blob.toString() + " 0 " + indexInfo;
        // update index
        String indexPath = objectsPath.substring(0, objectsPath.length() - 7) + "index";
        File index = new File(indexPath);

        // read info from index
        FileInputStream fileInputStream = new FileInputStream(index);
        byte[] contents = new byte[fileInputStream.available()];
        fileInputStream.read(contents);
        String value = new String(contents);


        // check if duplicated
        boolean is_dup = false;
        String[] indexValue = value.split(" ");
        for(String str : indexValue)
        {
            if( str.equals(key))
            {
                is_dup = true;
                break;
            }
        }

        if( !is_dup)
            value += indexInfo + "\n";

        // rewrite index

        FileOutputStream fileOutputStream = new FileOutputStream(index);
        contents = value.getBytes(StandardCharsets.UTF_8);
        fileOutputStream.write(contents);
        fileOutputStream.flush();
        fileOutputStream.close();


    }

    public static void treeHash(File file,String objectsPath) throws Exception {
        File[] files = file.listFiles();
        List<File> fileList = Tree.sortFile(files);
        // hash all sub-file
        for (File f : fileList) {
            JitHash.hash(f.getPath(), objectsPath);
        }
        // hash tree
        Tree tree = new Tree(file);
        String key = tree.getKey();
        if (key.length() != 40) {
            throw new IOException("hash value length error!");
        }

        // create folder
        String hashDir=objectsPath+ File.separator + key.substring(0, 2);
        if (!new File(hashDir).exists()) {
            FileCreation.createDirectory(objectsPath, key.substring(0, 2));
        }
        // create hash file
        String hashFile = hashDir + File.separator + key.substring(2);
        if (!new File(hashFile).exists()) {
            FileCreation.createFile(hashDir, key.substring(2), "");
        }
        // overwrite hash file
        tree.compressWrite(hashFile, tree);
    }

    /**
     * hash a file, write to hashDir.
     *
     * @param filename
     * @throws IOException
     */
    public static void hash(String filename,String objectsPath) throws Exception {
        int length = objectsPath.length();
        String indexPath = objectsPath.substring(0, length - 7);
        File index = new File(indexPath + "index");
        if( !index.exists())
        {
            FileCreation.createFile(indexPath, "index", "");
            // use Zlib compress index
            //FileOutputStream fileOutputStream = new FileOutputStream(index);
            //byte[] data = byteArrayOutputStream.toByteArray();
            //ZLibUtils.compress(data, fileOutputStream);
        }

        File file = new File(filename);
        //Blob hash
        if (file.isFile()) {
            blobHash(file,objectsPath);
        }
        //Tree hash
        if (file.isDirectory()) {
            treeHash(file,objectsPath);
        }
    }

    public static JitObject[] getObjectFromIndex(File file)
    {
        //byte[] data =
        return new JitObject[] {};
    }
}
